//kurs/wp-content/plugins/courses/js/html_parser.js
(function(){
    var startTag=/^<(\w+)((?:\s+\w+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
endTag=/^<\/(\w+)[^>]*>/,attr=/(\w+)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
var empty=makeMap("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed");
var block=makeMap("a,address,applet,blockquote,button,center,dd,del,dir,div,dl,dt,fieldset,form,frameset,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,p,pre,script,table,tbody,td,tfoot,th,thead,tr,ul");
var inline=makeMap("abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
var closeSelf=makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
var fillAttrs=makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
var special=makeMap("script,style");var HTMLParser=this.HTMLParser=function(html,handler){
var index,chars,match,stack=[],last=html;stack.last=function(){return this[this.length-1];};
while(html){chars=true;if(!stack.last()||!special[stack.last()]){if(html.indexOf("<!--")==0){
index=html.indexOf("-->");if(index>=0){if(handler.comment)handler.comment(html.substring(4,index));
html=html.substring(index+3);chars=false;}}else if(html.indexOf("</")==0){match=html.match(endTag);
if(match){html=html.substring(match[0].length);match[0].replace(endTag,parseEndTag);chars=false;}}else if(
 html.indexOf("<")==0){match=html.match(startTag);if(match){html=html.substring(match[0].length);
 match[0].replace(startTag,parseStartTag);chars=false;}}if(chars){index=html.indexOf("<");
 var text=index<0?html:html.substring(0,index);html=index<0?"":html.substring(index);
if(handler.chars)handler.chars(text);}}else{html=html.replace(new RegExp("(.*)<\/"+stack.last()+"[^>]*>"),function(all,text){
text=text.replace(/<!--(.*?)-->/g,"$1").replace(/<!\[CDATA\[(.*?)]]>/g,"$1");if(handler.chars)handler.chars(text);
return"";});parseEndTag("",stack.last());}if(html==last)throw"Parse Error: "+html;last=html;}parseEndTag();
function parseStartTag(tag,tagName,rest,unary){if(block[tagName]){while(stack.last()&&inline[stack.last()]){parseEndTag("",stack.last());}}
if(closeSelf[tagName]&&stack.last()==tagName){parseEndTag("",tagName);}unary=empty[tagName]||!!unary;if(!unary)stack.push(tagName);
if(handler.start){var attrs=[];rest.replace(attr,function(match,name){var value=arguments[2]?arguments[2]:arguments[3]?arguments[3]:arguments[4]?arguments[4]:fillAttrs[name]?name:"";attrs.push({name:name,value:value,escaped:value.replace(/(^|[^\\])"/g,'$1\\\"')});});
if(handler.start)handler.start(tagName,attrs,unary);}}function parseEndTag(tag,tagName){if(!tagName)var pos=0;else
for(var pos=stack.length-1;pos>=0;pos--)if(stack[pos]==tagName)break;if(pos>=0){for(var i=stack.length-1;i>=pos;i--)
if(handler.end)handler.end(stack[i]);stack.length=pos;}}};function makeMap(str){var obj={},items=str.split(",");
for(var i=0;i<items.length;i++)obj[items[i]]=true;return obj;}

    this.HTMLtoXML = function( html ) {
    var results = "",pos,parflag=[],tt=0,vl,nm,json_str='',numc,tagtree=[],pf,imgpa;

        tagtree[0]=[];
        tagtree[0]['branch'] = 0;    //учет количества веток(этот параметр только у первого узла, база - 0)
        tagtree[0]['nc']=0;
        tagtree[0]['adr']=0;        //адрес данной ветки
        tagtree[0]['tag']='html';
        parflag.push(0);
        tt++;
        json_str+= '{"i":"0","tag":"html","text":"html","children":[';
    HTMLParser(html, {
        start: function( tag, attrs, unary ) {
             results += "<" + tag;      //открытие тэга
                              tt++;      // номер открытого тэга
               pf=0;
            parflag.push(tt);            //номер вталкивается в стэк
            tagtree[tt]=new Array();     //массив для параметров данного тэга
           tagtree[tt]['nc']=0;         //учет количества детей данной ветки
            tagtree[tt]['adr']=0;        //адрес данной ветки
            tagtree[tt]['tag']=tag;        //tag данной ветки

            if(parflag.length==1 && tt > 0){ //если в стэке имеется только один элемент
        tagtree[0]['branch']= parseInt(tagtree[0]['branch'])+1;         //значит это новая ветка
        tagtree[tt]['adr']= tagtree[0]['branch'];             //адресом является количество ветвей (начиная с 0)

          }else if(parflag.length > 1 && tt > 0){   // если это потомки ветки

            numc = parseInt(tagtree[parflag[parflag.length-2]]['nc']);       //количество детей на данной ветке
            tagtree[tt]['adr']= tagtree[parflag[parflag.length-2]]['adr'] + 'c' + numc; //формируем адрес нового потомка
            tagtree[parflag[parflag.length-2]]['nc']= parseInt(numc)+1;         //добавляем еще одного ребенка в данную ветку
           }

           //строка json для открытого тэга,ставим на всякий случай запятую, если далее будут еще параметры узла,
           // (потом уберем если не понадобится)
          json_str += '{"i":"' + tagtree[tt]['adr'] + '","tag":"' + tag + '","text":"' + tag + '",';

        for ( var i = 0; i < attrs.length; i++ ){
                results += " " + attrs[i].name + '="' + attrs[i].escaped + '"';

                nm = attrs[i].name;
                vl  = attrs[i].escaped;

            if(nm=='src' && jQuery('#img_opt').attr('checked')){ //если поставлена галочка в чекбоксе для пути к картинкам
            imgpa =base_url + jQuery('#img_path').val();
  var vl1,vl2;
  var data = vl;
  var e=/.*\/([\w\-\.]+\.[^#?\s]+?$)/;
  if (data.match(e)) {
    vl = imgpa+'/'+RegExp.$1;

}


            }
               json_str += '"' + 'd_' + nm + '":"' + vl + '", ';    //формирование строки атрибутов, (в конце строки - запятая). Сразу маркируем каждый атрибут префиксом d_
            }
        json_str += ' "children":['; //после строки параметров (если они есть) ставим параметр children. На всякий случай, если не понадобится - уберем
            //console.log(json_str + ' после строки параметров ' + tt);
        results += (unary ? "/" : "") + ">";

           if(unary){        //если унарный тег -
            parflag.pop();                     //удаляем  тэг из стэка
            json_str = json_str.substr(0,json_str.length-12);     // удаляем параметр children, унарный тег не может иметь потомков
            pos = json_str.lastIndexOf(',');                      // убираем последнюю запятую,
            json_str = json_str.substr(0,pos);
            json_str = rtrim(json_str);                                   //удаляем пробелы справа
            json_str += '},';                                  //закрываем скобкой } элемент json строки

               //console.log(json_str + ' после унарного ' + tt + '<-  tt     ' +  parflag[parflag.length-1] + '<- последний в стеке  ');
            }
        },

        end: function( tag ) {                          //закрытие тэга
           results += "</" + tag + ">";
            //console.log(tag + '<-tag     ' +parflag[parflag.length-1] + '<-  номер последнего в стеке ' + tt + '<- tt      ' +  parflag[parflag.length-1] + '<- последний в стеке  ');
          if(tt == parflag[parflag.length-1]){ //если закрываемый тег является последним в стэке, значит у него нет детей
             json_str = json_str.substr(0,json_str.length-13);  //удаляем параметр children
             pos = json_str.lastIndexOf(',');                   //удаляем последнюю запятую
            json_str = json_str.substr(0,pos);
            json_str += '},';                                      //закрываем скобкой } элемент json строки
              //console.log(json_str + ' закрытие листа ' + tt);

          }else{                                                       //если закрываемый тег не последний в стэке, то есть является дитем

            pos = json_str.lastIndexOf(',');
            json_str = json_str.substr(0,pos);
            json_str += ']},';
              //console.log(json_str + ' закрытие родителя ' + tt + '<-  tt     ' +  parflag[parflag.length-1] + '<- последний в стеке  ');
           }

            parflag.pop();
            pf=1;
        },

            chars: function( text ) {
            results += text;
                  
               if(!jQuery('#txt_opt').attr('checked')){
                text = trim(text);
               if(json_str.substr(json_str.length-13,13).indexOf('children')!=-1 && pf==0)json_str = json_str.substr(0,json_str.length-13);  //удаляем параметр children

                if(text==="" && pf==0){
                  json_str += '"txt_content":"",';     //добавляем просто название параметра
                  //console.log(json_str + ' после пустого текста ' + tt);
                }else if(text!=='' && pf==0){

                    json_str += '"txt_content":"' + text + '",';     //добавляем текст если он есть
                //console.log(json_str + ' после добавления текста ' + tt);
                }
                if(pf==0)json_str += ' "children":[';               //добавляем параметр children
                //console.log(json_str + ' после добавления текста и добавления children ' + tt);
               }
    },
        comment: function( text ) {
            results += "<!--" + text + "-->";
        }
    });

     pos = json_str.lastIndexOf(',');
      json_str = json_str.substr(0,pos);
        json_str = '[' + json_str + ']}]';
        //json_str = '[' + json_str + ']';
        //console.log(json_str + ' окончательный');
    return json_str + '|||' + results;
};
})();


function trim(s){return rtrim(ltrim(s));}
function ltrim(s){return s.replace(/^\s+/, '');}
function rtrim(s){return s.replace(/\s+$/, '');}